package com.zzyl.nursing.service.impl;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.ServiceProperty;
import com.huaweicloud.sdk.iotda.v5.model.ShowProductRequest;
import com.huaweicloud.sdk.iotda.v5.model.ShowProductResponse;
import com.zzyl.common.constant.Constants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.FamilyMemberDto;
import com.zzyl.nursing.dto.HealthyDataDto;
import com.zzyl.nursing.dto.UserLoginRequestDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.service.WechatService;
import com.zzyl.nursing.vo.FamilyElderVo;
import com.zzyl.nursing.vo.FamilyMemberElderVo;
import com.zzyl.nursing.vo.HealthyDataVo;
import com.zzyl.nursing.vo.LoginVo;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.service.IFamilyMemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import javax.servlet.http.HttpServletRequest;

/**
 * 老人家属Service业务层处理
 *
 * @author 陈舜涛
 * @date 2025-07-31
 */
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService {
    @Autowired
    private FamilyMemberMapper familyMemberMapper;

    @Autowired
    private WechatService wechatService;
    @Autowired
    private IoTDAClient client;

    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private DeviceDataServiceImpl deviceDataService;

    static List<String> DEFAULT_NICKNAME_PREFIX = ListUtil.of(
            "生活更美好",
            "大桔大利",
            "日富一日",
            "好柿开花",
            "柿柿如意",
            "一椰暴富",
            "大柚所为",
            "杨梅吐气",
            "天生荔枝"
    );
    @Autowired
    private TokenService tokenService;
    @Autowired
    private FamilyMemberElderMapper familyMemberElderMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Qualifier("redisTemplate")
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private DeviceDataMapper deviceDataMapper;


    /**
     * 查询老人家属
     *
     * @param id 老人家属主键
     * @return 老人家属
     */
    @Override
    public FamilyMember selectFamilyMemberById(Long id) {
        return getById(id);
    }

    /**
     * 查询家人列表
     *
     * @return 老人家属
     */
    @Override
    public List<FamilyMemberElderVo> selectFamilyMemberList() {
        return familyMemberElderMapper.selectFamilyMemberList();
    }

    /**
     * 新增老人家属
     *
     * @param familyMemberDto 老人家属
     * @return 结果
     */
    /**
     * 直接从 Token 中解析 userId（基于你生成 Token 时存入的 claims）
     *
     * @param request HttpServletRequest
     * @return userId（若解析失败返回 null）
     */

    @Override
    public void add(FamilyMemberDto familyMemberDto, HttpServletRequest request) {
        //判断内容是否为空
        if (ObjectUtil.isEmpty(familyMemberDto)) {
            throw new BaseException("内容不能为空");
        }
        //判断身份证格式是否正确
        if (familyMemberDto.getIdCard() != null && !isValidIdCard(familyMemberDto.getIdCard())) {
            // 身份证格式不正确，可以抛出异常或返回错误信息
            throw new IllegalArgumentException("身份证格式不正确");
        }
        //判断老人是否入住
        Elder elder = elderMapper.selectOne(Wrappers.<Elder>lambdaQuery().eq(Elder::getIdCardNo, familyMemberDto.getIdCard()));
        if (ObjectUtil.isEmpty(elder)) {
            throw new BaseException("老人未入住");
        }
        Long userId = tokenService.getUserIdFromToken(request);
        //判断是否绑定过这个老人
        FamilyMemberElder familyMemberElder1 = familyMemberElderMapper.selectOne(Wrappers.<FamilyMemberElder>lambdaQuery().eq(FamilyMemberElder::getFamilyMemberId, elder.getId()));
        if (ObjectUtil.isNotEmpty(familyMemberElder1)) {
            throw new BaseException("该老人已绑定");
        }
        FamilyMemberElder familyMemberElder = new FamilyMemberElder();
        familyMemberElder.setFamilyMemberId(userId);
        familyMemberElder.setElderId(elder.getId());
        familyMemberElder.setRemark(familyMemberDto.getRemark());
        familyMemberElderMapper.insert(familyMemberElder);
    }

    // 简单的格式验证（18位数字，最后一位可以是数字或X）
    public boolean isValidIdCard(String idCard) {
        if (idCard == null || idCard.isEmpty()) {
            return false;
        }

        String regex = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
        return idCard.matches(regex);
    }

    /**
     * 修改老人家属
     *
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int updateFamilyMember(FamilyMember familyMember) {
        return updateById(familyMember) ? 1 : 0;
    }

    /**
     * 批量删除老人家属
     *
     * @param ids 需要删除的老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除老人家属信息
     *
     * @param id 老人家属主键
     * @return 结果
     */
    @Override
    public void deleteFamilyMemberById(Long id) {
        familyMemberElderMapper.deleteById(id);
    }

    @Override
    public LoginVo login(UserLoginRequestDto userLoginRequestDto) {
        //1.根据appid、appsecret、code获取openid
        String openid = wechatService.getOpenid(userLoginRequestDto.getCode());
        //2.根据openid查询客户信息
        FamilyMember familyMember = this.getOne(Wrappers.<FamilyMember>lambdaQuery().eq(FamilyMember::getOpenId, openid));
        //3.判断客户是否为空，为空则创建用户并赋值openid
        if (ObjectUtil.isEmpty(familyMember)) {
            familyMember = FamilyMember.builder().openId(openid).build();
        }
        //4.获取手机号
        String phone = wechatService.getPhone(userLoginRequestDto.getPhoneCode());
        //5.新增或者更新用户信息
        saveOrUpdateFamilyMember(familyMember, phone);
        //6.生成token，将id和name封装到token里面返回
        Map<String, Object> params = new HashMap<>();
        params.put("userId", familyMember.getId());
        params.put("nickName", familyMember.getName());
        String token = tokenService.createToken(params);
        LoginVo loginVo = LoginVo.builder()
                .token(token)
                .nickName(familyMember.getName())
                .build();
        return loginVo;
    }

    /**
     * 获取家人列表
     *
     * @param pageNum  页码
     * @param pageSize 页大小
     * @return 用户列表
     */
    @Override
    public List<FamilyElderVo> listByPage(Integer pageNum, Integer pageSize, HttpServletRequest request) {
        //开启分页助手
        Long userId = tokenService.getUserIdFromToken(request);
        PageHelper.startPage(pageNum, pageSize);
        List<FamilyElderVo> byConditionAndPage = familyMemberElderMapper.listByPage(userId);
        Page<FamilyElderVo> p = (Page<FamilyElderVo>) byConditionAndPage;
        return p.getResult();
    }

    private void saveOrUpdateFamilyMember(FamilyMember familyMember, String phone) {
        //判断电话号码需不需要更换
        if (ObjectUtil.notEqual(phone, familyMember.getPhone())) {
            familyMember.setPhone(phone);
        }
        //根据id是否存在判断是新增还是更新
        if (ObjectUtil.isNotEmpty(familyMember.getId())) {
            updateById(familyMember);
            return;
        }
        // 3.id不存在，保存新用户
        // 随机组装昵称，词组+手机号后四位
        String nickName = DEFAULT_NICKNAME_PREFIX.get((int) (Math.random() * DEFAULT_NICKNAME_PREFIX.size()))
                + StringUtils.substring(familyMember.getPhone(), 7);
        familyMember.setName(nickName);
        this.save(familyMember);
    }

    @Override
    public List<HealthyDataVo> QueryDevicePropertyStatus(HealthyDataDto healthyDataDto) {
        ShowProductRequest request = new ShowProductRequest();
        request.setProductId(healthyDataDto.getProductKey());
        ShowProductResponse response = client.showProduct(request);
        //根据设备名称获取设备id
        Device device = deviceMapper.selectOne(Wrappers.<Device>lambdaQuery().eq(Device::getDeviceName, healthyDataDto.getDeviceName()));
        String iotId = device.getIotId();


        List<ServiceProperty> properties = response.getServiceCapabilities().get(0).getProperties();
        List<HealthyDataVo> healthyDataVoList = new ArrayList<>();
        properties.forEach(serviceProperty -> {
            HealthyDataVo healthyDataVo = new HealthyDataVo();
            healthyDataVo.setDataType(serviceProperty.getDataType());
            healthyDataVo.setIdentifier(serviceProperty.getPropertyName());
            healthyDataVo.setName(serviceProperty.getDescription());
            String jsonstr = JSONUtil.toJsonStr(redisTemplate.opsForHash().get(Constants.IOT_DEVICE_LAST_DATA, iotId));
            List<DeviceData> deviceDatalist = JSONUtil.toList(jsonstr, DeviceData.class);
            deviceDatalist.forEach(deviceData -> {
                if (deviceData.getFunctionId().equals(serviceProperty.getPropertyName())) {
                    String timeString = String.valueOf(deviceData.getAlarmTime());
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
                    LocalDateTime dateTime = LocalDateTime.parse(timeString, formatter);
                    long timestamp = dateTime.toInstant(ZoneOffset.UTC).toEpochMilli();
                    healthyDataVo.setTime(String.valueOf(timestamp));
                    healthyDataVo.setValue(deviceData.getDataValue());
                }
            });
            healthyDataVo.setUnit(serviceProperty.getUnit());
            healthyDataVoList.add(healthyDataVo);
        });
        return healthyDataVoList;
    }
    @Override
    public List<DayData> queryDeviceDataListByDay(String functionId, Long startTime, Long endTime, String iotId) {

        LocalDateTime startDataTime = Instant.ofEpochMilli(startTime).atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endDataTime = Instant.ofEpochMilli(endTime).atZone(ZoneId.systemDefault()).toLocalDateTime();
        List<DayData> ldd= deviceDataService.selectDeviceData(functionId, startDataTime, endDataTime, iotId);

        return ldd;
    }


    @Override
    public List<DayData> queryDeviceDataListByWeek(String functionId, Long startTime, Long endTime, String iotId) {
        LocalDateTime startDataTime = Instant.ofEpochMilli(startTime).atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endDataTime = Instant.ofEpochMilli(endTime).atZone(ZoneId.systemDefault()).toLocalDateTime();
        List<DayData> lwd = deviceDataMapper.selectDeviceDataWeek(functionId, startDataTime, endDataTime, iotId);
        return lwd;
    }
}
